/*!
// Testweb v0.4.0
// http://or-change.cn
// Copyright 2014 OrChange Inc. All rights reserved.
// Licensed under the GPL License.
*/

/**
 * This is template view engine, including the constructor of  the template and  
 * template View Pool Management.
 * tpm opens four methods like open、close、refresh、getTemplate to outside
 * @module controller
 * @requires OC
 * @requires $
 * @requires Template
 * @requires edit
 * @requires dict
 * @requires ppm
 * @requires dim
 * @requires jsrender
 * @requires $.serializeObject
 * @requires $.cookie
 * @example
 * 
 */
define(function (require, exports, module) {
	'use strict';
	var tvm,
		$ = require("lib/jquery/jquery"),
		OC = require("lib/core/oc"),
		Template = require("lib/class/template"),
		edit = require("model/editor"),
		dict = require("model/dictor"),
		ppm = require("model/ppm"),
		dim = require("model/remote");

	require("lib/jquery/jsrender");
	require("lib/jquery/jquery.serializeObject");
	require("lib/jquery/jquery.cookie");
	require("lib/jquery/jquery.jeegoocontext");
	require("lib/jquery/component");

	/**
	 * Template View Management.
	 * The task of template view management is managing templte view,
	 * including acquisition、assembly、confirming status.etc.
	 * @class tvm
	 * @final
	 */
	window.tvm = tvm = {
		/**
		 * template pool
		 * @property pool
		 * @type object
		 */
		pool: {},
		/**
		 * template model
		 * @property model
		 * @type object
		 */
		model: {
			ppm: ppm,
			tpm: exports,
			OC: OC,
			dim: dim,
			dict: dict,
			edit: edit
		}
	};
	/**
	 * Generate secure $ method for a controller
	 * @method jquery
	 * @param template_name {string}
	 * @return 
	**/
	tvm.jQuery = function (template_name) {
		return function (path) {
			var context = $("[tpl=" + template_name + "]");
			return $(path, context);
		};
	};
	/**
	 * Cache a new template to pool.
	 * @method cacheTemplate
	 * @param template_name {string} template_name connecting with "_template.html" returns
	 * a complete template filename.
	 * @param data {object} The date can be initialized when the first time we
	 * structure a template.
	 * @param no_callback {function} Mark no callback function.
	 * @param callback {function} The callback function can be initialized after rendering 
	 * when the first time we structure a  template. 
	 * A user defined performed action when the first time we structure a  template, which called in the cache method.
	 */
	tvm.cacheTemplate = function (template_name, data, no_callback, callback) {
		var that = this;
		//TODO 链接地址应该是可以被配置的,另外需要跨域，需要一个RESTful接口。
		$.get("/testweb/View/" + template_name + "_template.html", function (response) {
			if (no_callback === true) {
				that.pool[template_name] = new Template(template_name, response, data);
				callback.call(that);
			} else {
				require.async("controller/" + template_name, function (controller) {
					var actived_callback = controller.execute(template_name, tvm.jQuery(template_name), tvm.model);
					that.pool[template_name] = new Template(template_name, response, data, actived_callback);
					callback.call(that);
				});
			}
		});
	};
	/**
	 * Cache a new language package.
	 * @method cacheLang
	 * @param lang_name {string} 
	 * @param callback {function} 
	 */
	tvm.cacheLang = function (lang_name, callback) {
		var that = this;
		OC.pull("/testweb/json/lang_" + lang_name + ".json", function (lang_packs) {
			Template.prototype.lang_packs[lang_name] = lang_packs;
			callback.call(that);
		});
	};
	/**
	 * Get the names of all  templates.
	 * @method getAllTemplateName
	 * @returns {array} names
	 */
	tvm.getAllTemplateName = function () {
		var name, names = [];
		for (name in this.pool) {
			if (this.pool.hasOwnProperty(name)) {
				names.push(name);
			}
		}

		return names;
	};
	/**
	 * Get the names of all actived templates.
	 * @method getActiveTemplateName
	 * @returns {array} names
	 */
	tvm.getActiveTemplateName = function () {
		var name, names = [];
		for (name in this.pool) {
			if (this.pool.hasOwnProperty(name) && this.getTemplate(name).isActive()) {
				names.push(name);
			}
		}

		return names;
	};
	/**
	 * Get the appropriate template from the pool according the template_name.
	 * @method getTemplate
	 * @param template_name {string} 
	 * @returns {Template} 
	 */
	tvm.getTemplate = function (template_name) {
		return this.pool[template_name];
	};
	/**
	 * Check whether the template is cached or not according the template_name.
	 * @method isTemplateCached
	 * @param template_name {string}
	 * @returns {boolean} 
	 */
	tvm.isTemplateCached = function (template_name) {
		return this.pool.hasOwnProperty(template_name);
	};
	/**
	 * Check whether the language package is cached or not according the lang_name.
	 * @method isLanguageCached
	 * @param lang_name {string}
	 * @returns {boolean} 
	 */
	tvm.isLanguageCached = function (lang_name) {
		return Template.prototype.lang_packs.hasOwnProperty(lang_name);
	};
	/**
	 * Activate template.
	 * That is important method of MVC layer. It checks the caching conditions of language and template.
	 * Calling activated method of template when everything is ready.
	 * @method activateTemplate
	 * @param template_name {string} 
	 * @param [data] {object} 
	 * @param no_callback {boolean} 
	 */
	tvm.activateTemplate = function (template_name, data, no_callback) {
		var cur_lang = OC.cfg("CURRENT_LANG");
		// 已经激活的就没有任何动作
		// 断言：没有缓存的一定没激活
		if (this.isTemplateCached(template_name) && this.getTemplate(template_name).isActive()) {
			return false;
		}
		// 检查语言包是不是存在
		if (this.isLanguageCached(cur_lang)) {
			if (this.isTemplateCached(template_name)) {
				this.getTemplate(template_name).activeMe(data);
			} else {
				this.cacheTemplate(template_name, data, no_callback, function () {
					this.activateTemplate(template_name, data, no_callback);
				});
			}
		} else {
			this.cacheLang(cur_lang, function () {
				this.activateTemplate(template_name, data, no_callback);
			});
		}
	};
	/**
	 * Deactivate template.
	 * @method deactivateTemplate
	 * @param template_name {string} 
	 * @return {Template} 
	 */
	tvm.deactivateTemplate = function (template_name) {
		return tvm.getTemplate(template_name).deactiveMe();
	};
	/**
	 * Refresh all templates.
	 * @method refreshAll
	 * @return tvm {object}
	 */
	tvm.refreshAll = function () {
		var i, len,
			cur_lang = OC.cfg("CURRENT_LANG"),
			names = this.getActiveTemplateName();

		if (this.isLanguageCached(cur_lang)) {
			len = names.length;
			for (i = 0; i < len; i += 1) {
				this.getTemplate(names[i]).refreshMe();
			}
		} else {
			this.cacheLang(cur_lang, function () {
				this.refreshAll();
			});
		}
		return this;
	};
	/**
	 * Refresh specified template.
	 * @method refresh
	 * @param template_name {string} 
	 * @param [data] {object} 
	 */
	tvm.refresh = function (template_name, data) {
		var that = this,
			cur_lang = OC.cfg("CURRENT_LANG");
		if (this.isLanguageCached(cur_lang)) {
			this.getTemplate(template_name).refreshMe(data);
		} else {
			this.cacheLang(cur_lang, function () {
				that.refresh(template_name, data);
			});
		}
	};

	exports.open = function (template_name, data, no_callback) {
		tvm.activateTemplate(template_name, data, no_callback);
		
		return this;
	};
	exports.close = function (template_name) {
		tvm.deactivateTemplate(template_name);
	};
	exports.refreshAll = function () {
		tvm.refreshAll();
		
		return this;
	};
	exports.getTemplate = function (template_name) {
		return tvm.getTemplate(template_name);
		
		return this;
	};
	exports.refresh = function (template_name, data) {
		tvm.refresh(template_name, data);
		
		return this;
	};
});